import { v4 as uuidv4 } from "uuid";
import { ReactNode, useEffect, useRef } from "react";
import { motion } from "framer-motion";
import { cn } from "@/lib/utils";
import { useStreamContext } from "@/providers/Stream";
import { useState, FormEvent } from "react";
import { Button } from "../ui/button";
import { CustomCheckpoint, CustomMessage } from "./agent-inbox/types";
import { AssistantMessage, AssistantMessageLoading } from "./messages/ai";
import { useApi } from "@/providers/ApiProvider";
import { ChatMessage } from "@/lib/types";
import { useThreads } from "@/providers/Thread";
type Message = CustomMessage;
type Checkpoint = CustomCheckpoint;
import { HumanMessage } from "./messages/human";
import {
  DO_NOT_RENDER_ID_PREFIX,
  ensureToolCallsHaveResponses,
} from "@/lib/ensure-tool-responses";
import { LangGraphLogoSVG } from "../icons/langgraph";
import { TooltipIconButton } from "./tooltip-icon-button";
import {
  ArrowDown,
  LoaderCircle,
  PanelRightOpen,
  PanelRightClose,
  SquarePen,
  XIcon,
  Plus,
  CircleX,
} from "lucide-react";
import { useQueryState, parseAsBoolean } from "nuqs";
import { StickToBottom, useStickToBottomContext } from "use-stick-to-bottom";
import ThreadHistory from "./history";
import { toast } from "sonner";
import { useMediaQuery } from "@/hooks/useMediaQuery";
import { Label } from "../ui/label";
import { Switch } from "../ui/switch";
import { GitHubSVG } from "../icons/github";
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "../ui/tooltip";
import { useFileUpload } from "@/hooks/use-file-upload";
import { ContentBlocksPreview } from "./ContentBlocksPreview";
import {
  useArtifactOpen,
  ArtifactContent,
  ArtifactTitle,
  useArtifactContext,
} from "./artifact";

function StickyToBottomContent(props: {
  content: ReactNode;
  footer?: ReactNode;
  className?: string;
  contentClassName?: string;
}) {
  const context = useStickToBottomContext();
  return (
    <div
      ref={context.scrollRef}
      style={{ width: "100%", height: "100%" }}
      className={props.className}
    >
      <div
        ref={context.contentRef}
        className={props.contentClassName}
      >
        {props.content}
      </div>

      {props.footer}
    </div>
  );
}

function ScrollToBottom(props: { className?: string }) {
  const { isAtBottom, scrollToBottom } = useStickToBottomContext();

  if (isAtBottom) return null;
  return (
    <Button
      variant="outline"
      className={props.className}
      onClick={() => scrollToBottom()}
    >
      <ArrowDown className="h-4 w-4" />
      <span>Scroll to bottom</span>
    </Button>
  );
}

function OpenGitHubRepo() {
  return (
    <TooltipProvider>
      <Tooltip>
        <TooltipTrigger asChild>
          <a
            href="https://github.com/langchain-ai/agent-chat-ui"
            target="_blank"
            className="flex items-center justify-center"
          >
            <GitHubSVG
              width="24"
              height="24"
            />
          </a>
        </TooltipTrigger>
        <TooltipContent side="left">
          <p>Open GitHub repo</p>
        </TooltipContent>
      </Tooltip>
    </TooltipProvider>
  );
}

export function Thread() {
  const [artifactContext, setArtifactContext] = useArtifactContext();
  const [artifactOpen, closeArtifact] = useArtifactOpen();
  const { threads } = useThreads();
  // const api = useApi();

  const [threadId, _setThreadId] = useQueryState("threadId");
  const [chatHistoryOpen, setChatHistoryOpen] = useQueryState(
    "chatHistoryOpen",
    parseAsBoolean.withDefault(false),
  );
  const [hideToolCalls, setHideToolCalls] = useQueryState(
    "hideToolCalls",
    parseAsBoolean.withDefault(true),
  );
  // 添加自定义API模式状态
  const [useCustomApi, setUseCustomApi] = useQueryState(
    "useCustomApi",
    parseAsBoolean.withDefault(true),
  );
  const [input, setInput] = useState("");
  const {
    contentBlocks,
    setContentBlocks,
    handleFileUpload,
    dropRef,
    removeBlock,
    resetBlocks,
    dragOver,
    handlePaste,
  } = useFileUpload();
  const [firstTokenReceived, setFirstTokenReceived] = useState(false);
  const isLargeScreen = useMediaQuery("(min-width: 1024px)");

  const stream = useStreamContext();
  const messages = stream.messages;
  const isLoading = stream.isLoading;

  // 添加API相关状态
  const api = useApi();

  // 定义当前加载状态
  const currentIsLoading = useCustomApi ? api.isLoading : isLoading;

  // 定义当前消息列表
  const currentMessages = useCustomApi ? api.messages : messages;

  const lastError = useRef<string | undefined>(undefined);

  const setThreadId = (id: string | null) => {
    _setThreadId(id);

    // close artifact and reset artifact context
    closeArtifact();
    setArtifactContext({});
  };
  //初始化一个conversationId
  // setThreadId(uuidv4());
  useEffect(() => {
    if (!useCustomApi || !threadId) {
      // 如果不使用自定义API或没有threadId，清空消息
      if (useCustomApi) {
        api.clearMessages();
      }
      return;
    }

    // 从threads数据中查找对应的thread
    const currentThread = threads.find((t) => t.thread_id === threadId);
    if (currentThread && currentThread.messages) {
      // 将thread中的messages转换为ChatMessage格式并设置到api中
      const chatMessages: ChatMessage[] = currentThread.messages.map(
        (msg, index) => ({
          id: `${threadId}-${index}`,
          role: msg.role || (msg.content ? "user" : "assistant"),
          content: msg.content || "",
          type: msg.role === "user" ? "human" : "ai",
        }),
      );

      // 使用setMessages方法设置消息
      api.setMessages(chatMessages);
      console.log("Loading thread messages:", chatMessages);
    } else {
      // 如果在threads中找不到对应的threadId，清空消息
      api.clearMessages();
      console.log(`Thread with ID ${threadId} not found, clearing messages`);
    }
  }, [threadId, threads, useCustomApi]); // 移除api依赖项

  useEffect(() => {
    if (!stream.error) {
      lastError.current = undefined;
      return;
    }
    try {
      const message = (stream.error as any).message;
      if (!message || lastError.current === message) {
        // Message has already been logged. do not modify ref, return early.
        return;
      }

      // Message is defined, and it has not been logged yet. Save it, and send the error
      lastError.current = message;
      toast.error("An error occurred. Please try again.", {
        description: (
          <p>
            <strong>Error:</strong> <code>{message}</code>
          </p>
        ),
        richColors: true,
        closeButton: true,
      });
    } catch {
      // no-op
    }
  }, [stream.error]);

  // TODO: this should be part of the useStream hook
  const prevMessageLength = useRef(0);
  useEffect(() => {
    if (
      messages.length !== prevMessageLength.current &&
      messages?.length &&
      messages[messages.length - 1].type === "ai"
    ) {
      setFirstTokenReceived(true);
    }

    prevMessageLength.current = messages.length;
  }, [messages]);

  // 修改handleSubmit函数
  const handleSubmit = (e: FormEvent) => {
    e.preventDefault();
    if (
      (input.trim().length === 0 && contentBlocks.length === 0) ||
      currentIsLoading
    )
      return;
    setFirstTokenReceived(false);
  
    if (useCustomApi) {
      // 使用自定义API模式 - 从stream context获取userId
      const userId = stream.userId; // 从context获取统一的userId
      let conversationId;
      
      // 从threadId中提取conversationId或生成新的
      if (threadId && threadId.includes("@@")) {
        // 如果threadId已经包含userId@@conversationId格式
        const parts = threadId.split("@@");
        conversationId = parts[1];
      } else {
        // 生成新的conversationId
        conversationId = uuidv4();
        // 更新threadId为userId@@conversationId格式
        setThreadId(`${userId}@@${conversationId}`);
      }
      
      console.log(`handleSubmit conversationId: ${conversationId}`);
      api.sendMessageStream(input.trim(), userId, conversationId);
    } else {
      // 原有LangGraph模式的代码保持不变
      const newHumanMessage: Message = {
        id: uuidv4(),
        type: "human",
        content: [
          ...(input.trim().length > 0 ? [{ type: "text", text: input }] : []),
          ...contentBlocks,
        ] as Message["content"],
      };
  
      const toolMessages = ensureToolCallsHaveResponses(stream.messages);
      const context = 
        Object.keys(artifactContext).length > 0 ? artifactContext : undefined;
  
      stream.submit(
        { messages: [...toolMessages, newHumanMessage], context },
        {
          streamMode: ["values"],
          optimisticValues: (prev: any) => ({
            ...prev,
            context,
            messages: [
              ...(prev.messages ?? []),
              ...toolMessages,
              newHumanMessage,
            ],
          }),
        },
      );
    }
  
    setInput("");
    setContentBlocks([]);
  };

  const handleRegenerate = (
    parentCheckpoint: Checkpoint | null | undefined,
  ) => {
    // Do this so the loading state is correct
    prevMessageLength.current = prevMessageLength.current - 1;
    setFirstTokenReceived(false);
    stream.submit(undefined, {
      checkpoint: parentCheckpoint,
      streamMode: ["values"],
    });
  };

  // 将ChatMessage转换为CustomMessage格式的适配器函数
  const adaptChatMessageToMessage = (
    chatMessage: ChatMessage,
    index: number,
  ): CustomMessage => {
    return {
      id: `msg-${index}`,
      type: chatMessage.role === "user" ? "human" : "ai",
      content: [{ type: "text", text: chatMessage.content }],
    } as CustomMessage;
  };

  // renderMessages函数 - 在组件内部定义
  const renderMessages = () => {
    if (!currentMessages || currentMessages.length === 0) {
      return null;
    }

    if (useCustomApi) {
      // 自定义API模式下的消息渲染
      return (
        (currentMessages as ChatMessage[])
          // .filter(chatMessage => chatMessage.role === 'assistant') // 只显示AI角色的消息
          .map((chatMessage, index) => {
            const adaptedMessage = adaptChatMessageToMessage(
              chatMessage,
              index,
            );
            // console.log('adaptedMessage', adaptedMessage);
            if (chatMessage.role === "user") {
              return (
                <HumanMessage
                  key={`chat-${index}`}
                  message={adaptedMessage}
                  isLoading={false}
                />
              );
            } else if (chatMessage.role === "assistant") {
              return (
                <AssistantMessage
                  key={`chat-${index}`}
                  message={adaptedMessage}
                  isLoading={
                    currentIsLoading && index === currentMessages.length - 1
                  }
                  handleRegenerate={() => {
                    // 自定义API模式暂不支持重新生成
                    toast.info("自定义API模式暂不支持重新生成");
                  }}
                  // hideToolCalls={hideToolCalls}
                />
              );
            }
            return null;
          })
      );
    } else {
      // LangGraph模式下的消息渲染
      return (currentMessages as CustomMessage[])
        .filter((message) => {
          return !message.id?.startsWith(DO_NOT_RENDER_ID_PREFIX);
        })
        .map((message, index) => {
          if (message.type === "human") {
            return (
              <HumanMessage
                key={message.id}
                message={message}
                isLoading={false}
              />
            );
          } else if (message.type === "ai") {
            return (
              <AssistantMessage
                key={message.id}
                message={message}
                isLoading={isLoading && index === currentMessages.length - 1}
                handleRegenerate={handleRegenerate}
                hideToolCalls={hideToolCalls}
              />
            );
          }
          return null;
        });
    }
  };

  const chatStarted = !!threadId || !!messages.length;
  const hasNoAIOrToolMessages = !messages.find(
    (m) => m.type === "ai" || m.type === "tool",
  );

  return (
    <div className="flex h-screen w-full overflow-hidden">
      <div className="relative hidden lg:flex">
        <motion.div
          className="absolute z-20 h-full overflow-hidden border-r bg-white"
          style={{ width: 300 }}
          animate={
            isLargeScreen
              ? { x: chatHistoryOpen ? 0 : -300 }
              : { x: chatHistoryOpen ? 0 : -300 }
          }
          initial={{ x: -300 }}
          transition={
            isLargeScreen
              ? { type: "spring", stiffness: 300, damping: 30 }
              : { duration: 0 }
          }
        >
          <div
            className="relative h-full"
            style={{ width: 300 }}
          >
            <ThreadHistory />
          </div>
        </motion.div>
      </div>

      <div
        className={cn(
          "grid w-full grid-cols-[1fr_0fr] transition-all duration-500",
          artifactOpen && "grid-cols-[3fr_2fr]",
        )}
      >
        <motion.div
          className={cn(
            "relative flex min-w-0 flex-1 flex-col overflow-hidden",
            !chatStarted && "grid-rows-[1fr]",
          )}
          layout={isLargeScreen}
          animate={{
            marginLeft: chatHistoryOpen && isLargeScreen ? 300 : 0,
            width: chatHistoryOpen
              ? isLargeScreen
                ? "calc(100% - 300px)"
                : "100%"
              : "100%",
          }}
          // style={{
          //   transition: "margin-left 0.1s ease-in-out",
          // }}
          // 设置 motion 组件的过渡动画效果
          // 当 isLargeScreen 为 true 时，使用弹簧动画效果，刚度(stiffness)为 300，阻尼(damping)为 30，使动画有弹性的运动效果
          // 当 isLargeScreen 为 false 时，过渡动画持续时间设置为 0，即不显示过渡动画
          transition={
            isLargeScreen
              ? { type: "spring", stiffness: 400, damping: 30 }
              : { duration: 0 }
          }
        >
          {!chatStarted && (
            <div className="absolute top-0 left-0 z-10 flex w-full items-center justify-between gap-3 p-2 pl-4">
              <div>
                {(!chatHistoryOpen || !isLargeScreen) && (
                  <Button
                    className="hover:bg-gray-100"
                    variant="ghost"
                    onClick={() => setChatHistoryOpen((p) => !p)}
                  >
                    {chatHistoryOpen ? (
                      <PanelRightOpen className="size-5" />
                    ) : (
                      <PanelRightClose className="size-5" />
                    )}
                  </Button>
                )}
              </div>
              <div className="absolute top-2 right-4 flex items-center">
                <OpenGitHubRepo />
              </div>
            </div>
          )}
          {chatStarted && (
            <div className="relative z-10 flex items-center justify-between gap-3 p-2">
              <div className="relative flex items-center justify-start gap-2">
                <div className="absolute left-0 z-10">
                  {(!chatHistoryOpen || !isLargeScreen) && (
                    <Button
                      className="hover:bg-gray-100"
                      variant="ghost"
                      onClick={() => setChatHistoryOpen((p) => !p)}
                    >
                      {chatHistoryOpen ? (
                        <PanelRightOpen className="size-5" />
                      ) : (
                        <PanelRightClose className="size-5" />
                      )}
                    </Button>
                  )}
                </div>
                <motion.button
                  className="flex cursor-pointer items-center gap-2"
                  onClick={() => setThreadId(uuidv4())} //新开启一段会话
                  animate={{
                    marginLeft: !chatHistoryOpen ? 48 : 0,
                  }}
                  transition={{
                    type: "spring",
                    stiffness: 300,
                    damping: 30,
                  }}
                >
                  <LangGraphLogoSVG
                    width={32}
                    height={32}
                  />
                  <span className="text-xl font-semibold tracking-tight">
                    Agent Chat
                  </span>
                </motion.button>
              </div>

              <div className="flex items-center gap-4">
                <div className="flex items-center">
                  <OpenGitHubRepo />
                </div>
                <TooltipIconButton
                  size="lg"
                  className="p-4"
                  tooltip="New thread"
                  variant="ghost"
                  onClick={() => setThreadId(null)}
                >
                  <SquarePen className="size-5" />
                </TooltipIconButton>
              </div>

              <div className="from-background to-background/0 absolute inset-x-0 top-full h-5 bg-gradient-to-b" />
            </div>
          )}

          <StickToBottom className="relative flex-1 overflow-hidden">
            <StickyToBottomContent
              // 修改布局方式，确保footer始终可见
              className={cn(
                "absolute inset-0 flex flex-col overflow-y-scroll px-4",
                !chatStarted && "mt-[5vh] items-stretch justify-start",
                chatStarted && "justify-start", // 改为justify-start
              )}
              contentClassName="pt-8 pb-32 max-w-3xl mx-auto flex flex-col  w-full" // 增加底部padding到pb-32
              content={
                <>
                  {renderMessages()}

                  {/* 显示连接状态 */}
                  {useCustomApi && !api.isConnected && (
                    <div className="text-center text-sm text-red-500">
                      ⚠️ 自定义API连接失败，请检查后端服务
                    </div>
                  )}

                  {/* 显示错误信息 */}
                  {useCustomApi && api.error && (
                    <div className="text-center text-sm text-red-500">
                      错误: {api.error}
                    </div>
                  )}

                  {/* Special rendering case for interrupts */}
                  {!useCustomApi &&
                    hasNoAIOrToolMessages &&
                    !!stream.interrupt && (
                      <AssistantMessage
                        key="interrupt-msg"
                        message={undefined}
                        isLoading={isLoading}
                        handleRegenerate={handleRegenerate}
                      />
                    )}
                  {currentIsLoading && !firstTokenReceived && (
                    <AssistantMessageLoading />
                  )}
                </>
              }
              footer={
                <div className="flex flex-shrink-0 flex-col items-center gap-8 border-t bg-white">
                  {" "}
                  {/* 移除border-t类 */}
                  {!chatStarted && (
                    <>
                      <div className="flex w-full flex-col items-center gap-4 pt-4">
                        {/* <div className="flex items-center gap-3">
                          <LangGraphLogoSVG className="h-8 flex-shrink-0" />
                          <h1 className="text-2xl font-semibold tracking-tight">
                            Agent Chat
                          </h1>
                        </div> */}
                        {/* 在首页添加模式切换 */}
                        <div className="flex items-center justify-center">
                          <Switch
                            id="api-mode-home"
                            checked={useCustomApi ?? false}
                            onCheckedChange={setUseCustomApi}
                            className={`${
                              useCustomApi
                                ? "bg-blue-600 hover:bg-blue-500"
                                : "bg-green-600 hover:bg-green-500"
                            }`}
                          />
                        </div>
                      </div>

                      {/* 显示连接状态 */}
                      {/* {useCustomApi && (
                        <div className={`text-sm ${
                          api.isConnected ? 'text-green-600' : 'text-red-600'
                        }`}>
                          {api.isConnected ? '✅ 后端连接正常' : '❌ 后端连接失败'}
                        </div>
                      )} */}
                    </>
                  )}
                  <ScrollToBottom className="animate-in fade-in-0 zoom-in-95 absolute bottom-full left-1/2 mb-4 -translate-x-1/2" />
                  <div
                    ref={dropRef}
                    className={cn(
                      "bg-muted relative z-10 mx-auto mb-8 w-full max-w-3xl rounded-2xl shadow-xs transition-all",
                      dragOver
                        ? "border-primary border-2 border-dotted"
                        : "border border-solid",
                    )}
                  >
                    <form
                      onSubmit={handleSubmit}
                      className="mx-auto grid max-w-3xl grid-rows-[1fr_auto] gap-2"
                    >
                      <ContentBlocksPreview
                        blocks={contentBlocks}
                        onRemove={removeBlock}
                      />
                      <textarea
                        value={input}
                        onChange={(e) => setInput(e.target.value)}
                        onPaste={handlePaste}
                        onKeyDown={(e) => {
                          if (
                            e.key === "Enter" &&
                            !e.shiftKey &&
                            !e.metaKey &&
                            !e.nativeEvent.isComposing
                          ) {
                            e.preventDefault();
                            const el = e.target as HTMLElement | undefined;
                            const form = el?.closest("form");
                            form?.requestSubmit();
                          }
                        }}
                        placeholder="Type your message..."
                        className="field-sizing-content resize-none border-none bg-transparent p-3.5 pb-0 shadow-none ring-0 outline-none focus:ring-0 focus:outline-none"
                      />

                      {/* 底部按钮组容器,添加overflow-x-auto使其可以横向滚动 */}
                      <div className="flex items-center gap-6 overflow-x-auto p-2 pt-4">
                        <div className="flex min-w-max items-center gap-6">
                          {/* 模式切换开关 */}
                          <div className="flex items-center space-x-2">
                            <Switch
                              id="api-mode"
                              checked={useCustomApi ?? false}
                              onCheckedChange={setUseCustomApi}
                            />
                            <Label
                              htmlFor="api-mode"
                              className="text-sm whitespace-nowrap text-gray-600"
                            >
                              {useCustomApi ? "Custom API" : "LangGraph"}
                            </Label>
                          </div>

                          {/* 只在LangGraph模式下显示工具调用开关 */}
                          {!useCustomApi && (
                            <div className="flex items-center space-x-2">
                              <Switch
                                id="render-tool-calls"
                                checked={hideToolCalls ?? false}
                                onCheckedChange={setHideToolCalls}
                              />
                              <Label
                                htmlFor="render-tool-calls"
                                className="text-sm whitespace-nowrap text-gray-600"
                              >
                                Hide Tool Calls
                              </Label>
                            </div>
                          )}

                          {/* 文件上传 - 只在LangGraph模式下显示 */}
                          {!useCustomApi && (
                            <>
                              <Label
                                htmlFor="file-input"
                                className="flex cursor-pointer items-center gap-2"
                              >
                                <Plus className="size-5 text-gray-600" />
                                <span className="text-sm whitespace-nowrap text-gray-600">
                                  Upload PDF or Image
                                </span>
                              </Label>
                              <input
                                id="file-input"
                                type="file"
                                onChange={handleFileUpload}
                                multiple
                                accept="image/jpeg,image/png,image/gif,image/webp,application/pdf"
                                className="hidden"
                              />
                            </>
                          )}
                        </div>

                        {/* 提交/取消按钮 */}
                        <div className="ml-auto">
                          {currentIsLoading ? (
                            <Button
                              key="stop"
                              onClick={() => {
                                if (useCustomApi) {
                                  toast.info("API模式暂不支持取消操作");
                                } else {
                                  stream.stop();
                                }
                              }}
                              variant="outline"
                            >
                              <CircleX className="size-4" />
                              Cancel
                            </Button>
                          ) : (
                            <Button
                              key="send"
                              type="submit"
                              disabled={
                                input.trim().length === 0 &&
                                contentBlocks.length === 0
                              }
                            >
                              Send
                            </Button>
                          )}
                        </div>
                      </div>
                    </form>
                  </div>
                </div>
              }
            />
          </StickToBottom>
        </motion.div>

        {/* Artifact sidebar */}
        <div className="relative overflow-hidden border-l bg-white">
          {artifactOpen && (
            <div className="flex h-full flex-col">
              <div className="flex items-center justify-between border-b p-4">
                <ArtifactTitle />
                <Button
                  variant="ghost"
                  size="sm"
                  onClick={closeArtifact}
                >
                  <XIcon className="h-4 w-4" />
                </Button>
              </div>
              <div className="flex-1 overflow-auto">
                <ArtifactContent />
              </div>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}
